﻿/*!
 *  Copyright (c), 上海沃恩信息科技有限公司.
 *  All rights reserved.
 *  Licensed under BSD (https://www.pittypat.work/bsd.html).
 */

using System;
using System.Collections.Generic;
using System.IO;
using Pittypat;

namespace Waln.Authority.Authentication
{
    sealed class NavApp : INavApp
    {
        /// <summary>
        /// 从数据集合中创建完整的导航列表。
        /// </summary>
        /// <param name="apps">从数据服务中查询到的应用信息列表。</param>
        /// <param name="modules">从数据服务中查询到的模块信息列表。</param>
        /// <returns>一个要发送到客户端的导航列表。</returns>
        internal static NavList ToNavApps(DataList<Data.App> apps, DataList<Data.Module> modules)
        {
            if (apps == null || modules == null || apps.Count == 0 || modules.Count == 0)
            {
                return NavList.Empty;
            }

            var appList = new List<INavApp>(apps.Count);
            NavApp app = null;
            string developerCode = null;
            string appIdentifier = null;

            foreach (var appItem in apps)
            {
                if (appItem != null)
                {
                    developerCode = appItem.DeveloperCode.ToLower();
                    appIdentifier = appItem.Identifier.ToLower();

                    app = new NavApp(appItem, developerCode, appIdentifier);
                    appList.Add(app);

                    foreach (var moduleItem in modules)
                    {
                        if (moduleItem != null && moduleItem.AppId == appItem.Id)
                        {
                            app.modules.Add(new NavModule(moduleItem, developerCode, appIdentifier));
                        }
                    }
                }
            }

            return new NavList(appList);
        }

        private Data.App app;
        private @string? iconUrl;
        private IList<INavModule> modules;

        /// <summary>
        /// 使用应用信息、开发者代码和应用标识符初始化 NavApp 的新实例。
        /// </summary>
        /// <param name="app">应用信息。</param>
        /// <param name="developerCode">开发者代码小写形式，用于创建图标路径。</param>
        /// <param name="appIdentifier">应用标识符小写形式，用于创建图标路径。</param>
        private NavApp(Data.App app, string developerCode, string appIdentifier)
        {
            this.app = app;
            this.iconUrl = String.Format("~/com/{0}/{1}/app.png", developerCode, appIdentifier);
            this.modules = new List<INavModule>(app.ModuleCount ?? 0);
        }

        /// <summary>
        /// 获取应用描述。
        /// </summary>
        @string? INavApp.Description
        {
            get
            {
                return this.app.Description;
            }
        }

        /// <summary>
        /// 获取图标路径。
        /// </summary>
        @string? INavApp.IconUrl
        {
            get
            {
                return this.iconUrl;
            }
        }

        /// <summary>
        /// 获取应用的 Id。
        /// </summary>
        uuid? INavApp.Id
        {
            get
            {
                return this.app.Id;
            }
        }

        /// <summary>
        /// 获取应用中包含的模块项目列表。
        /// </summary>
        IList<INavModule> INavApp.Modules
        {
            get
            {
                return this.modules;
            }
        }

        /// <summary>
        /// 获取应用的名称。
        /// </summary>
        @string? INavApp.Name
        {
            get
            {
                return this.app.Name;
            }
        }

        /// <summary>
        /// 获取应用的版本号。
        /// </summary>
        @string? INavApp.Version
        {
            get
            {
                return this.app.Version;
            }
        }

        /// <summary>
        /// 将当前对象作为 JSON 字符串写入指定的文本流。
        /// </summary>
        /// <param name="writer">目标文本流。</param>
        /// <exception cref="global::System.ArgumentNullException">writer 是 null。</exception>
        void IJson.Write(TextWriter writer)
        {
            if (writer == null)
            {
                throw new global::System.ArgumentNullException("writer");
            }

            writer.Write('{');

            writer.Write("\"id\":");
            this.app.Id.Write(writer);
            writer.Write(',');
            
            writer.Write("\"name\":");
            this.app.Name.Write(writer);
            writer.Write(',');

            writer.Write("\"version\":");
            this.app.Version.Write(writer);
            writer.Write(',');

            writer.Write("\"description\":");
            this.app.Description.Write(writer);
            writer.Write(',');

            writer.Write("\"iconUrl\":");
            this.iconUrl.Write(writer);
            writer.Write(',');
            
            writer.Write("\"modules\":[");

            if (this.modules != null && this.modules.Count > 0)
            {
                for (int i = 0; i < this.modules.Count; i++)
                {
                    this.modules[i].Write(writer);

                    if (i < this.modules.Count - 1)
                    {
                        writer.Write(',');
                    }
                }
            }

            writer.Write(']');

            writer.Write('}');
        }
    }
}
